#include <glib.h>
#include <gio/gio.h>
/*
int
main (int argc, char *argv[])
{
	g_setenv ("GSETTINGS_SCHEMA_DIR", ".", FALSE);
	g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
//(93.158.237.2:6697)
  gchar *ip = "93.158.237.2", *command = NULL, *nickname = "test",
        *channel_name = "#glib";
  gint port = 6697;
  gsize command_len = 0;
  GSocket *socket = NULL;
  GSocketAddress *address = NULL;
  GIOChannel *channel = NULL;
  GError *error = NULL;

  socket = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM,
      G_SOCKET_PROTOCOL_TCP, NULL);
  address = g_inet_socket_address_new_from_string (ip, port);
  g_socket_connect (socket, address, NULL, NULL);
  channel = g_io_channel_unix_new (g_socket_get_fd (socket));
//nick
  command = g_strdup_printf ("NICK %s\r\n", nickname);
  command_len = strlen (command);
  g_io_channel_write_chars (channel, command, command_len, NULL, &error);
  g_free (command);
//join
  command = g_strdup_printf ("JOIN %s\r\n", channel_name);
  command_len = strlen (command);
  g_io_channel_write_chars (channel, command, command_len, NULL, &error);
  g_free (command);
//response
  gchar *response = NULL;
  gsize response_len = 0;
  GIOStatus status;

  do {
    status = g_io_channel_read_line (channel, &response, &response_len,
        NULL, &error);
    g_warning ("invalid response:%s, status:%d\n", response, status);
    sleep (2);
  } while (1);
 // } while ((status == G_IO_STATUS_NORMAL) && (response_len <= 2));
  g_warning ("invalid response:%s, status:%d\n", response, status);
  g_warning ("error:%s\n", error->message);
//parse
  GStrv args = NULL;
  gchar *response_type = NULL;

  args = g_strsplit (response, " ", -1);
  response_type = args[1];
  if (!g_strcmp0 (response_type, "JOIN")) {
  } else if (!g_strcmp0 (response_type, "PART")) {
  } else if (!g_strcmp0 (response_type, "NICK")) {
  } else {
    g_warning ("invalid response:%s\n", response);
    g_warning ("invalid response type:%s\n", response_type);
  }
//shut down
  g_io_channel_shutdown (channel, TRUE, NULL);
  g_socket_close (socket, NULL);

  return 0;
}
*/
#include <gio/gio.h>
#include <string.h>

#define MAX_BUF_SIZE 1024

static gboolean
accept_certificate (GTlsClientConnection *conn,
                    GTlsCertificate      *cert,
                    GTlsCertificateFlags  errors,
                    gpointer              user_data)
{
  g_print ("Certificate would have been rejected ( ");
  if (errors & G_TLS_CERTIFICATE_UNKNOWN_CA)
    g_print ("unknown-ca ");
  if (errors & G_TLS_CERTIFICATE_BAD_IDENTITY)
    g_print ("bad-identity ");
  if (errors & G_TLS_CERTIFICATE_NOT_ACTIVATED)
    g_print ("not-activated ");
  if (errors & G_TLS_CERTIFICATE_EXPIRED)
    g_print ("expired ");
  if (errors & G_TLS_CERTIFICATE_REVOKED)
    g_print ("revoked ");
  if (errors & G_TLS_CERTIFICATE_INSECURE)
    g_print ("insecure ");
  g_print (") but accepting anyway.\n");

  return TRUE;
}
static void send_message(GOutputStream *out, const gchar *message) {
    GError *error = NULL;
    gsize length = strlen(message);

    g_output_stream_write(out, message, length, NULL, &error);
    if (error != NULL) {
        g_print("Failed to send login command: %s\n", error->message);
        g_error_free(error);
        return 1;
    } else {
        g_print("Sent: %s", message);
    }
    /*
        
    if (g_io_channel_write_chars(out, message, length, NULL, &error) == G_IO_ERROR_NONE) {
        g_print("Sent: %s", message);
    } else {
        g_printerr("Error sending message: %s\n", error->message);
        g_error_free(error);
    }
    */
}
static gboolean read_message(GInputStream *in)
{
    gchar *line = NULL;
    gsize length = 0;
    GError *error = NULL;
    gchar buf[MAX_BUF_SIZE] = {0};

    length = g_input_stream_read(in, buf, MAX_BUF_SIZE, NULL, &error);
    if (error != NULL) {
        g_print("Failed to receive join response: %s\n", error->message);
        g_error_free(error);
        return 1;
    } else {
        g_print("Received: %s", buf);
        //g_free(line);
    }

    return TRUE;
}
static gboolean read_cb(GIOChannel *source, GIOCondition condition, gpointer data) {
    gchar *line = NULL;
    gsize length = 0;
    GError *error = NULL;

    if (g_io_channel_read_line(source, &line, &length, NULL, &error) == G_IO_ERROR_NONE) {
        g_print("Received: %s", line);
        g_free(line);
    } else {
        g_printerr("Error reading from server: %s\n", error->message);
        g_error_free(error);
        return FALSE;
    }

    return TRUE;
}
int main(int argc, char *argv[]) {
    g_type_init();
    GError *error = NULL;
    GSocketClient *client = g_socket_client_new();
    GIOStream *tls_connection = NULL;
    GSocketConnection *connection = g_socket_client_connect_to_host(client,
        "irc.libera.chat", 6697, NULL, &error);
    if (error != NULL) {
        g_print("Failed to connect to IRC server: %s\n", error->message);
        g_error_free(error);
        return 1;
    }

    GSocket *socket = g_socket_connection_get_socket(connection);
    g_socket_set_blocking(socket, FALSE);

    tls_connection = g_tls_client_connection_new(G_IO_STREAM(connection), NULL, &error);
    if (error != NULL) {
        g_print("Failed to create TLS connection: %s\n", error->message);
        g_error_free(error);
        return 1;
    }
    g_signal_connect (tls_connection, "accept-certificate",
                      G_CALLBACK (accept_certificate), NULL);
    //g_tls_client_connection_set_validation_flags(tls_connection, G_TLS_CERTIFICATE_VALIDATE_NONE);
    gboolean result = g_tls_connection_handshake(G_TLS_CONNECTION (tls_connection),
        NULL, &error);
    if (!result) {
        g_print("Failed to perform TLS handshake: %s\n", error->message);
        g_error_free(error);
        return 1;
    }
    /*
    static GIOChannel *channel;
    channel = g_io_channel_unix_new(g_socket_get_fd(socket));
    g_io_channel_set_close_on_unref(channel, TRUE);
    g_io_channel_ref(channel);
    g_io_add_watch(channel, G_IO_IN, read_cb, NULL);

    send_message(channel, "NICK mynick\r\n");
    send_message(channel, "USER myuser 0 * :My User\r\n");
    gchar *join_cmd = g_strdup_printf("JOIN %s\r\n", channel);
    send_message(channel, join_cmd);

    GMainLoop *loop = g_main_loop_new(NULL, FALSE);
    g_main_loop_run(loop);

    g_io_channel_unref(channel);
    g_object_unref(tls_connection);
    g_object_unref(connection);
    g_object_unref(client);

    return 0;
    */
    GInputStream *input_stream = g_io_stream_get_input_stream(G_IO_STREAM(tls_connection));
    GOutputStream *output_stream = g_io_stream_get_output_stream(G_IO_STREAM(tls_connection));

    send_message(output_stream, "NICK mynick\r\n");
    send_message(output_stream, "USER myuser 0 * :My User\r\n");
    gchar *join_cmd = g_strdup_printf("JOIN %s\r\n", "#my_channel");
    send_message(output_stream, join_cmd);
    while (1) {
      if (read_message(input_stream)) {
        send_message(output_stream, "PRIVMSG #my_channel :hello irc\r\n");
      }
    }
    /*
    // 发送登录命令
    gchar *nick = "my_nick";
    gchar *user = "my_user";
    gchar *realname = "My Real Name";
    gchar *login_cmd = g_strdup_printf("USER %s 0 * :%s\r\nNICK %s\r\n",
        user, realname, nick);
    g_output_stream_write(output_stream, login_cmd, strlen(login_cmd), NULL, &error);
    g_free(login_cmd);

    // 接收登录成功消息
    gchar buf[MAX_BUF_SIZE];
    gssize len = g_input_stream_read(input_stream, buf, MAX_BUF_SIZE, NULL, &error);
    if (error != NULL) {
        g_print("Failed to receive login response: %s\n", error->message);
        g_error_free(error);
        return 1;
    }
    buf[len] = '\0';
    g_print("Received login response: %s\n", buf);

    // 加入频道
    gchar *channel = "#my_channel";
    gchar *join_cmd = g_strdup_printf("JOIN %s\r\n", channel);
    g_output_stream_write(output_stream, join_cmd, strlen(join_cmd), NULL, &error);
    if (error != NULL) {
        g_print("Failed to send join command: %s\n", error->message);
        g_error_free(error);
        return 1;
    }
    g_free(join_cmd);
    */
    static GIOChannel *channel;
    channel = g_io_channel_unix_new(g_socket_get_fd(socket));
    g_io_add_watch(channel, G_IO_IN, read_cb, NULL);
    //send_message("NICK mynick\r\n");
    //send_message("USER myuser 0 * :My User\r\n");
    while (1) {
      sleep (1);
    }
    GMainLoop *loop = g_main_loop_new(NULL, FALSE);
    g_main_loop_run(loop);

    g_io_channel_shutdown(channel, TRUE, &error);
    /*
    while (1) {
      // 接收加入频道成功消息
      len = g_input_stream_read(input_stream, buf, MAX_BUF_SIZE, NULL, &error);
      if (error != NULL) {
          g_print("Failed to receive join response: %s\n", error->message);
          g_error_free(error);
          return 1;
      }
      buf[len] = '\0';
      g_print("Received join response: %s\n", buf);
      sleep (1);
      g_output_stream_write(output_stream, "hello", 5, NULL, &error);
      if (error != NULL) {
          g_print("Failed to send join command: %s\n", error->message);
          g_error_free(error);
          return 1;
      }
    }
    */

    // 在这里可以使用input_stream和output_stream发送和接收IRC协议消息

    g_object_unref(tls_connection);
    g_object_unref(connection);
    g_object_unref(client);

    return 0;
}

